/*
 * @Author: peng.chen2 peng.chen2@rt-mart.com
 * @Date: 2025-07-24 10:30:00
 * @LastEditors: peng.chen2
 * @LastEditTime: 2025-07-31 11:09:46
 * @FilePath: /rt-monitoring/src/service/request.ts
 * @Description: Axios 请求封装
 */

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import { ApiResponse, RequestInterceptor, ResponseInterceptor } from './types'
import { API_BASE_URL } from '../config/env'

class HttpClient {
  private instance: AxiosInstance
  private baseURL: string

  constructor(baseURL: string = API_BASE_URL) {
    this.baseURL = baseURL
    this.instance = axios.create({
      baseURL,
      timeout: 10000,
      headers: {
        'Content-Type': 'application/json',
      },
    })

    this.setupInterceptors()
  }

  // 设置拦截器
  private setupInterceptors() {
    // 请求拦截器
    this.instance.interceptors.request.use(
      config => {
        // 添加认证 token
        const token = localStorage.getItem('token')
        if (token) {
          config.headers.Authorization = `Bearer ${token}`
        }

        // 添加时间戳防止缓存
        if (config.method === 'get') {
          config.params = {
            ...config.params,
            _t: Date.now(),
          }
        }

        console.log(
          '🚀 Request:',
          config.method?.toUpperCase(),
          config.url,
          config
        )
        return config
      },
      error => {
        console.error('❌ Request Error:', error)
        return Promise.reject(error)
      }
    )

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response: AxiosResponse<ApiResponse>) => {
        console.log('✅ Response:', response.config.url, response.data)

        const { data } = response

        // 统一处理业务错误
        if (data.code !== 200 && data.code !== 0) {
          console.error('❌ Business Error:', data.msg)
          // 这里可以添加全局错误提示
          return Promise.reject(new Error(data.msg || '请求失败'))
        }

        return response
      },
      error => {
        console.error('❌ Response Error:', error)

        // 处理 HTTP 错误状态码
        if (error.response) {
          const { status, data } = error.response

          switch (status) {
            case 401:
              // 未授权，清除 token 并跳转登录
              localStorage.removeItem('token')
              window.location.href = '/login'
              break
            case 403:
              console.error('❌ 403: 权限不足')
              break
            case 404:
              console.error('❌ 404: 接口不存在')
              break
            case 500:
              console.error('❌ 500: 服务器内部错误')
              break
            default:
              console.error(`❌ ${status}: ${data?.message || '请求失败'}`)
          }
        } else if (error.request) {
          console.error('❌ Network Error: 网络连接失败')
        }

        return Promise.reject(error)
      }
    )
  }

  // 添加请求拦截器
  public addRequestInterceptor(interceptor: RequestInterceptor) {
    this.instance.interceptors.request.use(
      interceptor.onFulfilled,
      interceptor.onRejected
    )
  }

  // 添加响应拦截器
  public addResponseInterceptor(interceptor: ResponseInterceptor) {
    this.instance.interceptors.response.use(
      interceptor.onFulfilled,
      interceptor.onRejected
    )
  }

  // 通用请求方法
  public async request<T = any>(
    config: AxiosRequestConfig
  ): Promise<ApiResponse<T>> {
    try {
      const response = await this.instance.request<ApiResponse<T>>(config)
      return response.data
    } catch (error) {
      throw error
    }
  }

  // GET 请求
  public async get<T = any>(
    url: string,
    params?: any,
    config?: AxiosRequestConfig
  ) {
    return this.request<T>({
      method: 'GET',
      url,
      params,
      ...config,
    })
  }

  // POST 请求
  public async post<T = any>(
    url: string,
    data?: any,
    config?: AxiosRequestConfig
  ) {
    return this.request<T>({
      method: 'POST',
      url,
      data,
      ...config,
    })
  }

  // PUT 请求
  public async put<T = any>(
    url: string,
    data?: any,
    config?: AxiosRequestConfig
  ) {
    return this.request<T>({
      method: 'PUT',
      url,
      data,
      ...config,
    })
  }

  // DELETE 请求
  public async delete<T = any>(
    url: string,
    params?: any,
    config?: AxiosRequestConfig
  ) {
    return this.request<T>({
      method: 'DELETE',
      url,
      params,
      ...config,
    })
  }

  // PATCH 请求
  public async patch<T = any>(
    url: string,
    data?: any,
    config?: AxiosRequestConfig
  ) {
    return this.request<T>({
      method: 'PATCH',
      url,
      data,
      ...config,
    })
  }

  // 上传文件
  public async upload<T = any>(
    url: string,
    file: File,
    onProgress?: (progress: number) => void
  ) {
    const formData = new FormData()
    formData.append('file', file)

    return this.request<T>({
      method: 'POST',
      url,
      data: formData,
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      onUploadProgress: progressEvent => {
        if (onProgress && progressEvent.total) {
          const progress = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          )
          onProgress(progress)
        }
      },
    })
  }

  // 下载文件
  public async download(
    url: string,
    filename?: string,
    params?: any
  ): Promise<void> {
    try {
      const response = await this.instance.get(url, {
        params,
        responseType: 'blob',
      })

      const blob = new Blob([response.data])
      const downloadUrl = window.URL.createObjectURL(blob)
      const link = document.createElement('a')
      link.href = downloadUrl
      link.download = filename || 'download'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
      window.URL.revokeObjectURL(downloadUrl)
    } catch (error) {
      console.error('❌ Download Error:', error)
      throw error
    }
  }
}

// 创建默认实例
export const httpClient = new HttpClient()

// 导出类以便创建其他实例
export { HttpClient }
export default httpClient
